package com.abe.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;

import com.abe.strengthtrainer.R;

/** 需要设置的参数：曲线view宽度移动的时间，上升时间，下降时间 */
public class CustomCurveView extends View implements Runnable {

	protected Context mContext;
	/** 画笔 */
	private Paint mPaint;
	/** 画笔宽 */
	private int paintWidth;
	/** 画笔颜色 */
	private int paintColor;
	/** view高度 */
	private float mHeight;
	/** view宽度 */
	private float mWitdh;
	/******** 曲线相关 ********/
	private boolean isDraw = false;

	public CustomCurveView(Context context) {
		this(context, null);
	}

	public CustomCurveView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public CustomCurveView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		paintColor = getResources().getColor(R.color.app_theme_color);
		/** 画笔宽度,并进行适配 */
		paintWidth = 0;
		mContext = context;
		init();
	}

	/**
	 * 由于onDraw()方法会不停的绘制 所以需要定义一个初始化画笔方法 避免导致不停创建造成内存消耗过大
	 */
	private void init() {
		mPaint = new Paint();
		setPaint();
	}

	/** 设置画笔 */
	private void setPaint() {
		/** 设置画笔为抗锯齿 */
		mPaint.setAntiAlias(true);
		/** 设置颜色 */
		mPaint.setColor(paintColor);
		/**
		 * 画笔样式分三种： 1.Paint.Style.STROKE：描边 2.Paint.Style.FILL_AND_STROKE：描边并填充
		 * 3.Paint.Style.FILL：填充
		 */
		mPaint.setStyle(Paint.Style.STROKE);
		/**
		 * 设置描边的粗细，单位：像素px 注意：当setStrokeWidth(0)的时候描边宽度并不为0而是只占一个像素
		 */
		mPaint.setStrokeWidth(paintWidth);
		/** path中所有线段的Join方式设置为ROUND,实际效果就是拟合处变成了更加平滑的曲线 */
		mPaint.setStrokeJoin(Paint.Join.ROUND);
	}

	@Override
	public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		mHeight = this.getMeasuredHeight();
		mWitdh = this.getMeasuredWidth();
	}

	@Override
	public void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		super.onLayout(changed, left, top, right, bottom);
		/** 主要作用 ：为将整个根据子视图的大小以及布局参数将View树放到合适的位置上 */
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		if (isDraw) {
			canvas.drawPath(getMovePath(), mPaint);
		}
	}

	@Override
	public void run() {
		isDraw = true;
		/** 通知刷新 */
		postInvalidate();
	}

	/** 长度统一单位为(px)，时间单位统一为(ms) ，速度统一单位为(px/ms) */
	/** 等待： 一组锻炼的开始的准备时间 */
	private int preparaTime = 0;
	/** 推举：开始位置至最大幅度时间 */
	private int pushTime = 0;
	/** 保持：最高位置保持时间 */
	private int keepMaxTime = 0;
	/** 回撤：最大幅度至开始位置时间 */
	private int returnTime = 0;
	/** 组时间 */
	private int groupTime = 0;
	/** 屏幕横向平移速度 */
	private float screenSpeed = 0;
	/** 屏幕横向平移时间 */
	private int screenMoveTime;
	/** 动态生成显示组数 */
	private int groupNum;
	/** 曲线最小Y坐标 */
	private float minHeight;
	/** 曲线最大Y坐标 */
	private float maxHeight;
	/** 所处屏幕位置，默认处于第一块屏幕 */
	private int screenNum = 1;

	/** 获取当前时间的动态Path */
	private Path getMovePath() {
		/*******************************************************************/
		/** 设置曲线峰顶 */
		maxHeight = (float) paintWidth / (float) 2;
		/** 设置曲线峰谷 */
		minHeight = (float) mHeight - (float) paintWidth / (float) 2;
		/** 计算显示组数 */
		groupNum = screenMoveTime / groupTime
				+ ((screenMoveTime % groupTime == 0) ? 0 : 1);
		/** 速度 */
		screenSpeed = (mWitdh / screenMoveTime);
		/*******************************************************************/
		Path path = new Path();
		int yTime = (screenMoveTime * (screenNum - 1)) % groupTime;
		float groupLen = (groupTime) * screenSpeed;
		/** 计算出起点前一个高点与低点以及起点后groupNum个高点与groupNum个低点 */
		/** 当前组高点X与低点X */
		float fristCenterPointLow0X = -yTime * screenSpeed;
		float fristCenterPointLow1X = (preparaTime - yTime) * screenSpeed;
		float fristCenterPointHigh0X = fristCenterPointLow1X + pushTime
				* screenSpeed;
		float fristCenterPointHigh1X = fristCenterPointHigh0X + keepMaxTime
				* screenSpeed;
		/** 上一组 */
		float previousCenterPointLow0X = fristCenterPointLow0X - groupLen;
		float previousCenterPointLow1X = fristCenterPointLow1X - groupLen;
		float previousCenterPointHigh0X = fristCenterPointHigh0X - groupLen;
		float previousCenterPointHigh1X = fristCenterPointHigh1X - groupLen;
		path.moveTo(previousCenterPointLow0X, minHeight);
		path.lineTo(previousCenterPointLow1X, minHeight);
		path.lineTo(previousCenterPointHigh0X, maxHeight);
		path.lineTo(previousCenterPointHigh1X, maxHeight);
		/** 后续组 */
		for (int i = 0; i < groupNum + 1; i++) {
			float addGroupX = i * groupLen;
			float tempCenterPointLow0X = fristCenterPointLow0X + addGroupX;
			float tempCenterPointLow1X = fristCenterPointLow1X + addGroupX;
			float tempCenterPointHigh0X = fristCenterPointHigh0X + addGroupX;
			float tempCenterPointHigh1X = fristCenterPointHigh1X + addGroupX;
			path.lineTo(tempCenterPointLow0X, minHeight);
			path.lineTo(tempCenterPointLow1X, minHeight);
			path.lineTo(tempCenterPointHigh0X, maxHeight);
			path.lineTo(tempCenterPointHigh1X, maxHeight);
		}
		return path;
	}

	public int getPreparaTime() {
		return preparaTime;
	}

	/** 等待： 一组锻炼的开始的准备时间 */
	public void setPreparaTime(int preparaTime) {
		this.preparaTime = preparaTime;
		updateGroupTime();
	}

	public int getPushTime() {
		return pushTime;
	}

	/** 推举：开始位置至最大幅度时间 */
	public void setPushTime(int pushTime) {
		this.pushTime = pushTime;
		updateGroupTime();
	}

	public int getKeepMaxTime() {
		return keepMaxTime;
	}

	/** 保持：最高位置保持时间 */
	public void setKeepMaxTime(int keepMaxTime) {
		this.keepMaxTime = keepMaxTime;
		updateGroupTime();
	}

	public int getReturnTime() {
		return returnTime;
	}

	/** 回撤：最大幅度至开始位置时间 */
	public void setReturnTime(int returnTime) {
		this.returnTime = returnTime;
		updateGroupTime();
	}

	public int getGroupTime() {
		return groupTime;
	}

	private void updateGroupTime() {
		this.groupTime = preparaTime + pushTime + keepMaxTime + returnTime;
	}

	public int getScreenMoveTime() {
		return screenMoveTime;
	}

	public void setScreenMoveTime(int screenMoveTime) {
		this.screenMoveTime = screenMoveTime;
	}

	public float getScreenSpeed() {
		return screenSpeed;
	}

	public int getPaintWidth() {
		return paintWidth;
	}

	public void setPaintWidth(int paintWidth) {
		this.paintWidth = paintWidth;
		setPaint();
	}

	public int getPaintColor() {
		return paintColor;
	}

	public void setPaintColor(int paintColor) {
		this.paintColor = paintColor;
		setPaint();
	}

	public int getScreenNum() {
		return screenNum;
	}

	/** 设置小球屏幕位置 */
	public void setScreenNum(int screenNum) {
		this.screenNum = screenNum;
	}

	/** 获取最小Y坐标 */
	public float getMinHeight() {
		return minHeight;
	}

	/** 获取最大Y坐标 */
	public float getMaxHeight() {
		return maxHeight;
	}

}
